package repository

import (
	"blog_go/internal/model"
	"errors"
	"time"
)

type ArticleCommentRepository interface {
	QueryComment(articleId int, userId int) ([]*model.ArticleCommentTreeList, error)
	QueryAllComment(userId int, userType int) ([]*model.ArticleCommentManage, error)
	AddComment(comment model.ArticleComment) error
	DelComment(commentId int, userId int, userType int) error
	ReviewComment(commentIds []int, status int) error
	ReviewAllComment() error
	LikeArticleComment(commentId int, userId int) error
	UnLikeArticleComment(commentId int, userId int) error
	DisLikeArticleComment(commentId int, userId int) error
	UnDisLikeArticleComment(commentId int, userId int) error
}

type articleCommentRepository struct {
	*BaseRepository
}

func NewArticleCommentRepository(repository *BaseRepository) ArticleCommentRepository {
	return &articleCommentRepository{
		BaseRepository: repository,
	}
}

// 查询文章的评论
func (r *articleCommentRepository) QueryComment(articleId int, userId int) ([]*model.ArticleCommentTreeList, error) {
	comments := make([]*model.ArticleCommentTreeList, 0)

	query := " WITH RECURSIVE cte AS ( " +
		" SELECT a1.comment_id, a1.article_id, a1.user_id, a1.content, a1.create_time, a1.comment_parent_id, likes, a1.dislikes, a1.status, " +
		" COALESCE(f1.file_path, '') 'filePath', u1.display_name, COALESCE(u3.display_name, '') 'parentDisplayName', 0 As level, a1.root_parent_id, " +
		" CASE WHEN EXISTS (SELECT 1 FROM comment_like WHERE comment_id = a1.comment_id AND comment_like.user_id = ?) THEN 'true' ELSE 'false' END as is_liked, " +
		" CASE WHEN EXISTS (SELECT 1 FROM comment_dislike WHERE comment_id = a1.comment_id AND comment_dislike.user_id = ?) THEN 'true' ELSE 'false' END as is_disliked " +
		" FROM article_comment a1 LEFT JOIN user u1 ON u1.user_id = a1.user_id " +
		" LEFT JOIN user u3 ON u3.user_id = a1.comment_parent_id " +
		" LEFT JOIN fileinfo f1 ON u1.img_file_id = f1.file_id " +
		" WHERE a1.comment_parent_id = 0 " +

		" UNION ALL " +
		" SELECT a2.comment_id, a2.article_id, a2.user_id, a2.content, a2.create_time, a2.comment_parent_id, a2.likes, a2.dislikes, a2.status, " +
		" COALESCE(f2.file_path, '') 'filePath', u2.display_name, COALESCE(u4.display_name, '') 'parentDisplayName', cte.level + 1 , a2.root_parent_id, " +
		" CASE WHEN EXISTS (SELECT 1 FROM comment_like WHERE comment_id = a2.comment_id AND comment_like.user_id = ?) THEN 'true' ELSE 'false' END as is_liked, " +
		" CASE WHEN EXISTS (SELECT 1 FROM comment_dislike WHERE comment_id = a2.comment_id AND comment_dislike.user_id = ?) THEN 'true' ELSE 'false' END as is_disliked " +
		" FROM article_comment a2 JOIN cte ON cte.comment_id = a2.comment_parent_id " +
		" LEFT JOIN user u2 ON u2.user_id = a2.user_id " +
		" LEFT JOIN user u4 ON u4.user_id = cte.user_id " +
		" LEFT JOIN fileinfo f2 ON u2.img_file_id = f2.file_id) " +
		" SELECT * FROM cte WHERE article_id = ? AND status = 1 "

	rows, err := r.db.Query(query, userId, userId, userId, userId, articleId)
	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var comment model.ArticleCommentTreeList

		err = rows.Scan(&comment.CommentId, &comment.ArticleId, &comment.UserId, &comment.Content, &comment.CreateTime, &comment.CommentParentId,
			&comment.Like, &comment.DisLike, &comment.Status, &comment.FilePath, &comment.DisplayName, &comment.ParentDisplayName, &comment.Level, &comment.RootParentId,
			&comment.IsLiked, &comment.IsDisLiked)

		if err != nil {
			return nil, err
		}

		comments = append(comments, &comment)
	}

	tree := ArticleCommentTree(comments, 0)

	return tree, nil
}

// 评论递归
func ArticleCommentTree(node []*model.ArticleCommentTreeList, parentId int) []*model.ArticleCommentTreeList {
	res := make([]*model.ArticleCommentTreeList, 0)
	for _, v := range node {
		if v.RootParentId == parentId {
			v.Children = ArticleCommentTree(node, v.CommentId)
			res = append(res, v)
		}
	}
	return res
}

// 查询所有评论
func (r *articleCommentRepository) QueryAllComment(userId int, userType int) ([]*model.ArticleCommentManage, error) {
	comments := make([]*model.ArticleCommentManage, 0)

	query := `
		SELECT 
			ac.comment_id, 
			ac.article_id, 
			ac.user_id, 
			ac.content, 
			ac.create_time, 
			ac.comment_parent_id,
			ac.likes, 
			ac.dislikes, 
			ac.status, 
			COALESCE(f.file_path, '') 'filePath', 
			u.display_name, 
			a.title, 
			u1.display_name
		FROM 
			article_comment ac 
		LEFT JOIN 
			user u 
		ON u.user_id = ac.user_id
		LEFT JOIN 
			fileinfo f 
		ON u.img_file_id = f.file_id
		LEFT JOIN 
			article a 
		ON ac.article_id = a.article_id
		LEFT JOIN 
			user u1 
		ON u1.user_id = a.author_id`

	var queryParams []interface{}

	if userType == 1 {
		query += " WHERE ac.user_id = ?"
		queryParams = append(queryParams, userId)
	}

	query += " ORDER BY ac.status "

	rows, err := r.db.Query(query, queryParams...)
	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var comment model.ArticleCommentManage

		err := rows.Scan(&comment.CommentId, &comment.ArticleId, &comment.UserId, &comment.Content, &comment.CreateTime, &comment.CommentParentId,
			&comment.Like, &comment.DisLike, &comment.Status, &comment.FilePath, &comment.DisplayName, &comment.ArticleTitle, &comment.AuthorDisplayName)
		if err != nil {
			return nil, err
		}

		comments = append(comments, &comment)
	}

	return comments, nil
}

// 添加评论
func (r *articleCommentRepository) AddComment(comment model.ArticleComment) error {
	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	//初始化评论属性
	comment.Like = 0
	comment.DisLike = 0
	comment.CreateTime = time.Now().Format("2006-01-02 15:04:05")
	comment.Status = 0

	if comment.CommentParentId == 0 { //一级评论
		comment.RootParentId = 0
	} else {
		var parentId int
		var rootParentId int
		err = tx.QueryRow(`
			SELECT 
				comment_parent_id, 
				root_parent_id 
			FROM 
				article_comment 
			WHERE 
				comment_id = ?`, comment.CommentParentId).Scan(&parentId, &rootParentId)
		if err != nil {
			tx.Rollback()
			return err
		}

		if parentId == 0 { //二级评论
			comment.RootParentId = comment.CommentParentId
		} else { //三级以上评论
			comment.RootParentId = rootParentId
		}
	}

	_, err = tx.Exec(`
		INSERT INTO article_comment
		(
			user_id, 
			article_id, 
			content, 
			comment_parent_id, 
			create_time, 
			status, 
			likes, 
			dislikes, 
			root_parent_id
		) 
		VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
		comment.UserId, comment.ArticleId, comment.Content, comment.CommentParentId, comment.CreateTime, comment.Status, comment.Like, comment.DisLike, comment.RootParentId)
	if err != nil {
		return err
	}

	err = tx.Commit()
	return err
}

// 删除评论
func (r *articleCommentRepository) DelComment(commentId int, userId int, userType int) error {
	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	if userType == 1 {
		var authorId int
		err = tx.QueryRow(`
			SELECT 
				user_id 
			FROM 
				article_comment 
			WHERE 
				comment_id = ?`, commentId).Scan(&authorId)
		if err != nil {
			return err
		}

		if authorId != userId {
			return errors.New("用户无权限删除他人评论")
		}
	}

	// 计算需要删除的评论数量
	var deletedCount int
	err = tx.QueryRow(`
		SELECT 
			COUNT(*) 
		FROM 
			article_comment 
		WHERE 
			root_parent_id = ? 
		OR	comment_id = ?`, commentId, commentId).Scan(&deletedCount)
	if err != nil {
		return err
	}

	var articleId int
	err = tx.QueryRow(`
		SELECT 
			article_id 
		FROM 
			article_comment 
		WHERE 
			comment_id = ?`, commentId).Scan(&articleId)
	if err != nil {
		return err
	}

	_, err = tx.Exec(`
		DELETE FROM article_comment 
		WHERE 
			root_parent_id = ? 
		OR	comment_id = ?`, commentId, commentId)
	if err != nil {
		return err
	}

	_, err = tx.Exec(`
		UPDATE 
			article 
		SET 
			comment_count = comment_count - ? 
		WHERE 
			article_id = ?`, deletedCount, commentId)
	if err != nil {
		return err
	}

	err = tx.Commit()
	return err
}

// 审核评论
func (r *articleCommentRepository) ReviewComment(commentIds []int, status int) error {
	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	stmt1, err := tx.Prepare(`
		UPDATE 
			article_comment 
		SET 
			status = ? 
		WHERE 
			comment_id = ?
	`)
	if err != nil {
		return err
	}

	defer stmt1.Close()

	stmt2, err := tx.Prepare(`
		UPDATE 
			article 
		SET 
			comment_count = comment_count + 1 
		WHERE 
			article_id = ?
	`)
	if err != nil {
		return err
	}

	defer stmt2.Close()

	for _, commentId := range commentIds {
		_, err = stmt1.Exec(status, commentId)

		//如果评论通过,评论数 + 1
		var articleId int

		err = tx.QueryRow(`
			SELECT 
				article_id 
			FROM 
				article_comment 
			WHERE 
				comment_id = ?`, commentId).Scan(&articleId)
		if err != nil {
			return err
		}

		if status == 1 {
			_, err = stmt2.Exec(articleId)
		}
	}

	err = tx.Commit()
	return err
}

// 点赞评论
func (r *articleCommentRepository) LikeArticleComment(commentId int, userId int) error {
	//查询是否有反对评论并删除
	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	var count int

	err = tx.QueryRow(`
		SELECT 
			COUNT(*) 
		FROM 
			comment_like 
		WHERE 
			comment_id = ? 
		AND	user_id = ?`, commentId, userId).Scan(&count)
	if err != nil {
		return err
	}

	if count > 0 {
		return errors.New("该评论已点赞")
	}

	err = tx.QueryRow(`
		SELECT 
			COUNT(*) 
		FROM 
			comment_dislike 
		WHERE 
			comment_id = ? 
		AND	user_id = ?`, commentId, userId).Scan(&count)
	if err != nil {
		return err
	}

	if count > 0 {
		_, err = tx.Exec(`
			DELETE FROM comment_dislike 
			WHERE 
				user_id = ? 
			AND comment_id = ?`, userId, commentId)
		if err != nil {
			return err
		}

		_, err = tx.Exec(`
			UPDATE 
				article_comment 
			SET 
				dislikes = dislikes - 1 
			WHERE 
				comment_id = ?`, commentId)
		if err != nil {
			return err
		}
	}

	_, err = tx.Exec(`
		INSERT INTO comment_like
		(
			user_id, 
			comment_id
		) 
		VALUES (?, ?)`, userId, commentId)
	if err != nil {
		return err
	}

	_, err = tx.Exec(`
		UPDATE article_comment 
		SET 
			likes = likes + 1 
		WHERE 
			comment_id = ?`, commentId)
	if err != nil {
		return err
	}

	err = tx.Commit()
	return err
}

// 取消点赞评论
func (r *articleCommentRepository) UnLikeArticleComment(commentId int, userId int) error {
	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	var count int
	err = tx.QueryRow(`
		SELECT COUNT(*) 
		FROM comment_dislike 
		WHERE 
			comment_id = ? 
		AND user_id = ?`, commentId, userId).Scan(&count)

	if count > 0 {
		return errors.New("该评论已取消点赞")
	}

	_, err = tx.Exec(`
		DELETE FROM comment_like 
		WHERE 
			user_id = ? 
		AND comment_id = ?`, userId, commentId)
	if err != nil {
		return err
	}

	_, err = tx.Exec(`
		UPDATE 
			article_comment 
		SET 
			likes = likes - 1 
		WHERE 
			comment_id = ?`, commentId)
	if err != nil {
		return err
	}

	err = tx.Commit()
	return err
}

// 反对点赞评论
func (r *articleCommentRepository) DisLikeArticleComment(commentId int, userId int) error {
	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	var count int

	err = tx.QueryRow(`
		SELECT 
			COUNT(*) 
		FROM 
			comment_dislike 
		WHERE 
			comment_id = ? 
		AND user_id = ?`, commentId, userId).Scan(&count)
	if err != nil {
		return err
	}

	if count > 0 {
		return errors.New("该评论已反对")
	}

	err = tx.QueryRow(`
		SELECT 
			COUNT(*) 
		FROM 
			comment_like 
		WHERE 
			comment_id = ? 
		AND user_id = ?`, commentId, userId).Scan(&count)
	if err != nil {
		return err
	}

	if count > 0 {
		_, err = tx.Exec(`
			DELETE FROM comment_like 
			WHERE 
				user_id = ? 
			AND comment_id = ?`, userId, commentId)
		if err != nil {
			return err
		}

		_, err = tx.Exec(`
			UPDATE 
				article_comment 
			SET 
				likes = likes - 1 
			WHERE 
				comment_id = ?`, commentId)
		if err != nil {
			return err
		}
	}

	_, err = tx.Exec(`
		INSERT INTO comment_dislike
		(
			user_id, 
			comment_id
		) 
		VALUES(?, ?)`, userId, commentId)
	if err != nil {
		return err
	}

	_, err = tx.Exec(`
		UPDATE 
			article_comment 
		SET 
			dislikes = dislikes + 1 
		WHERE 
			comment_id = ?`, commentId)
	if err != nil {
		return err
	}

	err = tx.Commit()
	return err
}

// 取消反对评论
func (r *articleCommentRepository) UnDisLikeArticleComment(commentId int, userId int) error {
	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	_, err = tx.Exec(`
		DELETE FROM comment_dislike 
		WHERE 
			user_id = ? 
		AND comment_id = ?`, userId, commentId)
	if err != nil {
		return err
	}

	_, err = tx.Exec(`
		UPDATE 
			article_comment 
		SET 
			dislikes = dislikes - 1 
		WHERE comment_id = ?`, commentId)
	if err != nil {
		return err
	}

	err = tx.Commit()
	return err
}

// 一键审核
func (r *articleCommentRepository) ReviewAllComment() error {
	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	//统计未审核的评论
	articleIds := make(map[int]int)

	rows, err := tx.Query(`
		SELECT 
			article_id 
		FROM 
			article_comment 
		WHERE 
			status = 0
	`)
	if err != nil {
		return err
	}

	defer rows.Close()

	for rows.Next() {
		var articleId int

		err = rows.Scan(&articleId)
		if err != nil {
			return err
		}

		if count, exist := articleIds[articleId]; exist {
			articleIds[articleId] = count + 1
		} else {
			articleIds[articleId] = 1
		}
	}

	//一键审核评论
	_, err = tx.Exec(`
		UPDATE 
			article_comment 
		SET 
			status = 1 
		WHERE 
			status = 0
	`)
	if err != nil {
		return err
	}

	if len(articleIds) > 0 {
		stmt, err := tx.Prepare(`
			UPDATE 
				article 
			SET 
				comment_count = comment_count + ? 
			WHERE 
				article_id = ?
		`)
		if err != nil {
			return err
		}

		defer stmt.Close()

		for articleId, count := range articleIds {
			_, err = stmt.Exec(count, articleId)
			if err != nil {
				return err
			}
		}
	}

	err = tx.Commit()
	return err
}
